//MountManager - the program for easy mounting of storage devices in Linux
//Copyright (C) 2007-2008 Tikhonov Sergey
//
//This file is part of MountManager Plugin "Images mounting"
//
//This program is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation; either version 2
//of the License, or (at your option) any later version.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this program; if not, write to the Free Software
//Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
#include <QtGui/QDialog>
#include <QtGui/QAction>
#include <QtGui/QGridLayout>
#include <QtGui/QPushButton>
#include <QtGui/QComboBox>
#include <QtGui/QLineEdit>
#include <QtGui/QLabel>
#include <QtGui/QCheckBox>
#include <QtGui/QFileDialog>
#include <QtCore/QDir>
#include <QtCore/QUrl>
#include <QtPlugin>
#include <QDesktopServices>
#include "imagesmounting.h"

ImagesMounting::ImagesMounting(QWidget *parent) {
	mainWidget = new QDialog(parent);

	// To define open or not mount point directory after mounting
	wasMounting = false;

	homePath = QDir::homePath();
	if (!QDir(homePath + "/.mountmanager/").exists())
		QDir().mkpath(homePath + "/.mountmanager/");
	tempIsoImagePath = homePath + "/.mountmanager/temp_isoimage.iso";
	
	process = new QProcess(this);
	connect(process,SIGNAL(finished(int,QProcess::ExitStatus)),this,SLOT(processFinished(int,QProcess::ExitStatus)));
	
	QAction *action = new QAction(this);
	action->setText(tr("Images mounting"));
	action->setIcon(QIcon(":/icons/main.png"));
	connect(action,SIGNAL(triggered()),mainWidget,SLOT(show()));
	actions.append(action);
	
	mountButton = new QPushButton(tr("Mount"));
	connect(mountButton,SIGNAL(clicked()),this,SLOT(mount()));
	
	unmountButton = new QPushButton(tr("Unmount"));
	connect(unmountButton,SIGNAL(clicked()),this,SLOT(unmount()));
	
	closeButton = new QPushButton(tr("Close"));
	connect(closeButton,SIGNAL(clicked()),mainWidget,SLOT(hide()));

	imagePath = new QLineEdit;
	mountPointPath = new QLineEdit;
	chooseMountPointPath = new QPushButton;
	chooseMountPointPath->setIcon(QIcon(":/icons/choose.png"));
	connect(chooseMountPointPath,SIGNAL(clicked()),this,SLOT(chooseMountPoint()));
	
	chooseImagePath = new QPushButton;
	chooseImagePath->setIcon(QIcon(":/icons/choose.png"));
	connect(chooseImagePath,SIGNAL(clicked()),this,SLOT(chooseImage()));

	openDirAfterMounting = new QCheckBox(tr("Open directory after mounting"));

	QHBoxLayout *buttonsLayout = new QHBoxLayout;
	buttonsLayout->addStretch();
	buttonsLayout->addWidget(mountButton);
	buttonsLayout->addWidget(unmountButton);
	buttonsLayout->addWidget(closeButton);

	QGridLayout *gridLayout = new QGridLayout;
	gridLayout->addWidget(new QLabel(tr("Choose image") + ":"),0,0);
	gridLayout->addWidget(imagePath,0,1);
	gridLayout->addWidget(chooseImagePath,0,2);
	gridLayout->addWidget(new QLabel(tr("Choose mount point") + ":"),1,0);
	gridLayout->addWidget(mountPointPath,1,1);
	gridLayout->addWidget(chooseMountPointPath,1,2);
	gridLayout->setColumnStretch(1,1);
	
	QVBoxLayout *mainLayout = new QVBoxLayout;
	mainLayout->addLayout(gridLayout);
	mainLayout->addWidget(openDirAfterMounting);
	mainLayout->addStretch();
	mainLayout->addLayout(buttonsLayout);
	mainWidget->setLayout(mainLayout);
	mainWidget->setWindowTitle(tr("Images mounting"));
	mainWidget->setWindowIcon(QIcon(":/icons/main.png"));
	mainWidget->resize(500,mainWidget->sizeHint().height());
}

ImagesMounting::~ImagesMounting() {
	delete mainWidget;
	foreach (QAction *action,actions)
		delete action;
	delete mountButton;
	delete unmountButton;
	delete closeButton;
	delete imagePath;
	delete mountPointPath;
	delete chooseImagePath;
	delete chooseMountPointPath;
	delete openDirAfterMounting;
}

void ImagesMounting::setParent(QObject *parent) {
	connect(this,SIGNAL(showError(const QString&)),parent,SLOT(showError(const QString &)));
}

const QString ImagesMounting::pluginName() const {
	return tr("Images mounting");
}

const QString ImagesMounting::pluginDescription() const {
	return tr("With help of this plugin you can mount images of different formats from Nero to Iso");
}
	
QDialog* ImagesMounting::dialog() const {
	return mainWidget;
}

QDockWidget* ImagesMounting::dockWidget() const {
	return 0;
}

QMenu* ImagesMounting::menu() const {
	return 0;
}

QToolBar* ImagesMounting::toolBar() const {
	return 0;
}

Actions ImagesMounting::menuActions() const {
	return actions;
}

void ImagesMounting::chooseImage() {
	QString path = QFileDialog::getOpenFileName(mainWidget,tr("Choose image"),homePath,tr("Images formats (*.iso *.nrg *.bin *.mdf *.ccd *.img *.sub *.b5i *.cdi *.pdi *.dmg)"));
	if (path.isEmpty())
		return;
	imageType = QFileInfo(path).fileName().split(".").last();
	imagePath->setText(path);
}

void ImagesMounting::chooseMountPoint() {
	QString path = QFileDialog::getExistingDirectory(mainWidget,tr("Choose mount point"),"/mnt");
	if (path.isEmpty())
		return;
	mountPointPath->setText(path);
}

void ImagesMounting::mount() {
	if (imagePath->text().isEmpty()) {
		imagePath->setFocus();
		return;
	}
	if (mountPointPath->text().isEmpty()) {
		mountPointPath->setFocus();
		return;
	}
	if (imageType != "iso" && convert()) {
		wasMounting = true;
		process->start(QString("mount -t iso9660 -o loop \"%1\" \"%2\"").arg(tempIsoImagePath).arg(mountPointPath->text()));
	}
	else if (imageType == "iso") {
		process->start(QString("mount -t iso9660 -o loop \"%1\" \"%2\"").arg(imagePath->text()).arg(mountPointPath->text()));
		wasMounting = true;
	}
}

bool ImagesMounting::convert() {
	process->waitForFinished();
	QString program;
	// Define the program for converting to iso
	if (imageType.isEmpty() && QFileInfo(imagePath->text()).fileName().split(".").count() > 1)
		imageType = QFileInfo(imagePath->text()).fileName().split(".").last();
	if (imageType.isEmpty()) {
		emit(showError(tr("[%1] File name is invalid.").arg(pluginName())));
		return false;
	}
	if (imageType == "nrg")
		program = "nrg2iso";
	else if (imageType == "bin" || imageType == "cue")
		program = "bchunk";
	else if (imageType == "mdf")
		program = "mdf2iso";
	else if (imageType == "img" || imageType == "ccd" || imageType == "sub")
		program = "ccd2iso";
	else if (imageType == "b5i")
		program = "b5i2iso";
	else if (imageType == "cdi")
		program = "cdi2iso";
	else if (imageType == "pdi")
		program = "pdi2iso";
	else if (imageType == "dmg")
		program = "dmg2iso";
	if (program.isEmpty())
		return false;
	process->start(QString("%1 \"%2\" \"%3\"").arg(program).arg(imagePath->text()).arg(tempIsoImagePath));
	if (process->readAllStandardError().isEmpty())
		return true;
	emit(showError(tr("[%1] Cannot to convert your image to iso image. Maybe image is corrupted").arg(pluginName())));
	return false;
}

void ImagesMounting::processFinished(int exitCode,QProcess::ExitStatus) {
	if (exitCode != 0)
		emit(showError(tr("[%1] We are sorry, but was error").arg(pluginName()) + ": " + QString::fromUtf8(process->readAllStandardError().data())));
	else if (wasMounting && openDirAfterMounting->isChecked())
		QDesktopServices::openUrl(QUrl(mountPointPath->text()));
	if (exitCode == 0 && wasMounting) {
		imagePath->clear();
		mountPointPath->clear();
	}
	wasMounting = false;
}

void ImagesMounting::unmount() {
	QString path = QFileDialog::getExistingDirectory(mainWidget,tr("Choose mount point"),"/mnt");
	if (path.isEmpty())
		return;
	process->start(QString("umount %1").arg(path));
}

Q_EXPORT_PLUGIN2(imagesmounting,ImagesMounting)
